#ifndef OBJFILE_H
#define OBJFILE_H

#include "imGeometry.h"
#include <string>
#include <vector>
#include <fstream>
#include <sstream>

/*
Wavefront Obj file parsing
*/

class ObjFile;
class ObjPrimitive;

namespace ObjData {
	// Vertex, refers to coordinates
	struct Point {
		union {
			struct {
				int Position, Texture, Normal;
			};
			int Data[3];
		};
	public:
		Point() {
			Position = Texture = Normal = 0;
		}

		bool operator==(const Point &v) {
			return 
				Position == v.Position &&
				Texture == v.Texture &&
				Normal == v.Normal;
		}
	};
	// Face, refers to different points
	struct Face {
		std::vector<Point> Points;
	};

	struct Object {
		std::string Name;
		std::vector<Face> Faces;
		std::string Mtrl;
	};

	struct Material {
	};
}

// ObjFile
// Parses file, produces smaller ObjPrimitives for use to build meshes
class ObjFile {
	std::vector<Vector3> m_Pos;
	std::vector<Vector2> m_Tex;
	std::vector<Vector3> m_Norm;
	std::vector<ObjData::Object> m_Objects;

	std::string m_MtrlLib;

	float m_fWorkArea[4];
protected:
	void m_ParseLine(std::istream &LineStr);
public:
	void Load(char* Path);
	void Build(ObjPrimitive &Prim);
};

class ObjPrimitive : public iPrimitive {
	std::vector<Vector3> *m_Pos;
	std::vector<Vector2> *m_Tex;
	std::vector<Vector3> *m_Norm;

	std::vector<ObjData::Point*> m_Points;
	
	template <typename Ind>
	void BuildIndices(ObjData::Object *Obj);

	Vertex BuildVertex(ObjData::Point *p);
	int GetVertexIndex(ObjData::Point *Point);
	
	void Clear();

public:
	ObjPrimitive();

	void SetParams(std::vector<Vector3> *Pos, std::vector<Vector2> *Tex, std::vector<Vector3> *Norm);
	void BuildObject(ObjData::Object *Obj);

	void Build();
};

#endif